/**
 * Created with CLion.
 * Description: 
 * User: loong
 * Date: 2025/4/18
 * Time: 22:31
 */

#include "Game.h"
#include "../SceneMain.h"
#include "../affiliate/sprite.h"
#include <SDL3_mixer/SDL_mixer.h>
#include <SDL3_ttf/SDL_ttf.h>
void Game::Run()
{
    while(is_running_) {
        auto start = SDL_GetTicksNS();
        HandleEvents();
        Update(dt_);
        Render();
        auto end     = SDL_GetTicksNS();
        if(auto elapsed = end - start; elapsed < frame_delay_) {
            SDL_DelayNS(frame_delay_ - elapsed);
            dt_ = frame_delay_ / 1.0e9;
        }
        else {
            dt_ = elapsed / 1.0e9;
        }
        // SDL_Log("FPS: %f", 1.0 / dt_);
    }
}

void Game::Init(const std::string & _title, int _width, int _height)
{
    screen_size_ = glm::vec2(_width, _height);
    // SDL3初始化
    if(!SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO)) {
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL初始化失败: %s\n", SDL_GetError());
    }
    // 不需要进行SDL_image初始化
    // SDL3_Mixer初始化
    if(Mix_Init(MIX_INIT_MP3 | MIX_INIT_OGG) != (MIX_INIT_MP3 | MIX_INIT_OGG)) {
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_Mixer初始化失败: %s\n", SDL_GetError());
    }
    if(!Mix_OpenAudio(0, nullptr)) {
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_Mixer打开音频失败: %s\n", SDL_GetError());
    }
    Mix_AllocateChannels(16);           // 分配16个音频通道
    Mix_VolumeMusic(MIX_MAX_VOLUME / 4);// 设置音乐音量
    Mix_Volume(-1, MIX_MAX_VOLUME / 4); // 设置音效音量

    // SDL3_TTF初始化
    if(!TTF_Init()) {
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "SDL_TTF初始化失败: %s\n", SDL_GetError());
    }
    // 创建窗口与渲染器
    SDL_CreateWindowAndRenderer(_title.c_str(), _width, _height, SDL_WINDOW_RESIZABLE, &window_, &renderer_);
    if(!window_ || !renderer_) {
        SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "创建窗口或渲染器失败: %s\n", SDL_GetError());
    }
    // 设置窗口逻辑分辨率
    SDL_SetRenderLogicalPresentation(renderer_, _width, _height, SDL_LOGICAL_PRESENTATION_LETTERBOX);

    // 计算帧延迟
    frame_delay_ = 1e9 / FPS_;

    asset_store_ = new AssetStore(renderer_);

    current_scene_ = new SceneMain();
    current_scene_->Init();
}

void Game::HandleEvents()
{
    SDL_Event event;
    while(SDL_PollEvent(&event)) {
        switch(event.type) {
            case SDL_EVENT_QUIT:
                is_running_ = false;
                break;
            default:
                current_scene_->HandleEvent(event);
                break;
        }
    }
}

void Game::Update(float dt)
{
    mouse_buttons_ = SDL_GetMouseState(&mouse_position_.x, &mouse_position_.y);
    current_scene_->Update(dt);
}

void Game::Render()
{
    SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 255);
    SDL_RenderClear(renderer_);
    current_scene_->Render();
    SDL_RenderPresent(renderer_);
}

void Game::Clean()
{
    if(nullptr != current_scene_) {
        current_scene_->Clean();
        delete current_scene_;
    }

    // 释放渲染器和窗口
    if(nullptr != renderer_)
        SDL_DestroyRenderer(renderer_);

    if(nullptr != window_)
        SDL_DestroyWindow(window_);
    // 退出Mix
    Mix_CloseAudio();
    Mix_Quit();
    // 退出TTF
    TTF_Quit();
    // 退出SDL
    SDL_Quit();
}

void Game::RenderTexture(const Texture & _texture, const glm::vec2 & _position, const glm::vec2 & _size)
{
    SDL_FRect dst_rect = {
            _position.x,
            _position.y,
            _size.x,
            _size.y};
    SDL_RenderTextureRotated(renderer_, _texture.texture, &_texture.src_rect, &dst_rect, _texture.angle, nullptr, _texture.is_flip ? SDL_FLIP_HORIZONTAL : SDL_FLIP_NONE);
}

void Game::RenderFillCircle(const glm::vec2 & _position, const glm::vec2 & _size, float _alpha)
{
    auto texture = asset_store_->GetImage("../assets/UI/circle.png");
    SDL_FRect dst_rect = {
        _position.x, _position.y, _size.x, _size.y
    };
    SDL_SetTextureAlphaModFloat(texture, _alpha);
    SDL_RenderTexture(renderer_, texture, nullptr, &dst_rect);
}

void Game::DrawGrid(const glm::vec2 & _top_left, const glm::vec2 & _bottom_right, float _grid_width, SDL_FColor _color)
{
    SDL_SetRenderDrawColorFloat(renderer_, _color.r, _color.g, _color.b, _color.a);
    for(float x = _top_left.x; x <= _bottom_right.x; x += _grid_width) {
        SDL_RenderLine(renderer_, x, _top_left.y, x, _bottom_right.y);
    }
    for(float y = _top_left.y; y <= _bottom_right.y; y += _grid_width) {
        SDL_RenderLine(renderer_, _top_left.x, y, _bottom_right.x, y);
    }
    SDL_SetRenderDrawColorFloat(renderer_, 0, 0, 0, 1);
}

void Game::DrawBoundary(const glm::vec2 & _top_left, const glm::vec2 & _bottom_right, float _boundary_width, SDL_FColor _fcolor)
{
    SDL_SetRenderDrawColorFloat(renderer_, _fcolor.r, _fcolor.g, _fcolor.b, _fcolor.a);
    for(float i = 0; i < _boundary_width; i++) {
        SDL_FRect rect = {
                _top_left.x - i,
                _top_left.y - i,
                _bottom_right.x - _top_left.x + 2 * i,
                _bottom_right.y - _top_left.y + 2 * i};
        SDL_RenderRect(renderer_, &rect);
    }
    SDL_SetRenderDrawColorFloat(renderer_, 0, 0, 0, 1);
}
